#include "User.h"
#include <crypt.h>
#include <random>
#include <chrono>
#include <sstream>
#include <iomanip>
#include <iostream>

namespace aod {

// TableUser 实现
std::string TableUser::HashPassword(const std::string& password) {
    // 简化：直接返回明文密码（仅用于开发测试）
    return password;
}

bool TableUser::VerifyPassword(const std::string& password, const std::string& stored_password) {
    // 简化：直接比较明文密码
    return (password == stored_password);
}

bool TableUser::Register(const std::string& username, const std::string& password, const std::string& email) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    // 检查用户名和邮箱是否已存在
    if (UsernameExists(username) || EmailExists(email)) {
        return false;
    }
    
    std::string hashed_password = HashPassword(password);
    
    std::stringstream sql;
    sql << "INSERT INTO users (username, password, email) VALUES ('"
        << username << "', '" << hashed_password << "', '" << email << "')";
    
    return MysqlQuery(_mysql, sql.str());
}

bool TableUser::Login(const std::string& username, const std::string& password, Json::Value* user_info) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    std::stringstream sql;
    sql << "SELECT user_id, username, password, email FROM users WHERE username='" << username << "'";
    
    if (!MysqlQuery(_mysql, sql.str())) {
        return false;
    }
    
    MYSQL_RES* res = mysql_store_result(_mysql);
    if (res == NULL) {
        return false;
    }
    
    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == NULL) {
        mysql_free_result(res);
        return false;
    }
    
    std::string stored_password = row[2];
    if (!VerifyPassword(password, stored_password)) {
        mysql_free_result(res);
        return false;
    }
    
    // 填充用户信息
    (*user_info)["user_id"] = atoi(row[0]);
    (*user_info)["username"] = row[1];
    (*user_info)["email"] = row[3];
    
    mysql_free_result(res);
    return true;
}

bool TableUser::GetUserById(int user_id, Json::Value* user_info) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    std::stringstream sql;
    sql << "SELECT user_id, username, email FROM users WHERE user_id=" << user_id;
    
    if (!MysqlQuery(_mysql, sql.str())) {
        return false;
    }
    
    MYSQL_RES* res = mysql_store_result(_mysql);
    if (res == NULL) {
        return false;
    }
    
    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == NULL) {
        mysql_free_result(res);
        return false;
    }
    
    (*user_info)["user_id"] = atoi(row[0]);
    (*user_info)["username"] = row[1];
    (*user_info)["email"] = row[2];
    
    mysql_free_result(res);
    return true;
}

bool TableUser::GetUserByUsername(const std::string& username, Json::Value* user_info) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    std::stringstream sql;
    sql << "SELECT user_id, username, email FROM users WHERE username='" << username << "'";
    
    if (!MysqlQuery(_mysql, sql.str())) {
        return false;
    }
    
    MYSQL_RES* res = mysql_store_result(_mysql);
    if (res == NULL) {
        return false;
    }
    
    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == NULL) {
        mysql_free_result(res);
        return false;
    }
    
    (*user_info)["user_id"] = atoi(row[0]);
    (*user_info)["username"] = row[1];
    (*user_info)["email"] = row[2];
    
    mysql_free_result(res);
    return true;
}

bool TableUser::UpdateUser(int user_id, const Json::Value& user_data) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    std::stringstream sql;
    sql << "UPDATE users SET ";
    
    bool first = true;
    if (user_data.isMember("email")) {
        sql << "email='" << user_data["email"].asString() << "'";
        first = false;
    }
    
    if (user_data.isMember("password")) {
        if (!first) sql << ", ";
        std::string hashed_password = HashPassword(user_data["password"].asString());
        sql << "password='" << hashed_password << "'";
    }
    
    sql << " WHERE user_id=" << user_id;
    
    return MysqlQuery(_mysql, sql.str());
}

bool TableUser::UsernameExists(const std::string& username) {
    std::stringstream sql;
    sql << "SELECT COUNT(*) FROM users WHERE username='" << username << "'";
    
    if (!MysqlQuery(_mysql, sql.str())) {
        return false;
    }
    
    MYSQL_RES* res = mysql_store_result(_mysql);
    if (res == NULL) {
        return false;
    }
    
    MYSQL_ROW row = mysql_fetch_row(res);
    int count = (row != NULL) ? atoi(row[0]) : 0;
    mysql_free_result(res);
    
    return count > 0;
}

bool TableUser::EmailExists(const std::string& email) {
    std::stringstream sql;
    sql << "SELECT COUNT(*) FROM users WHERE email='" << email << "'";
    
    if (!MysqlQuery(_mysql, sql.str())) {
        return false;
    }
    
    MYSQL_RES* res = mysql_store_result(_mysql);
    if (res == NULL) {
        return false;
    }
    
    MYSQL_ROW row = mysql_fetch_row(res);
    int count = (row != NULL) ? atoi(row[0]) : 0;
    mysql_free_result(res);
    
    return count > 0;
}

// TableUserSession 实现
std::string TableUserSession::GenerateSessionId() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 15);
    
    std::stringstream ss;
    for (int i = 0; i < 32; ++i) {
        ss << std::hex << dis(gen);
    }
    
    return ss.str();
}

bool TableUserSession::CreateSession(int user_id, std::string* session_id, std::string* expires_at) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    *session_id = GenerateSessionId();
    
    // 设置过期时间为24小时后
    auto now = std::chrono::system_clock::now();
    auto expires = now + std::chrono::hours(24);
    auto expires_time_t = std::chrono::system_clock::to_time_t(expires);
    
    std::stringstream ss;
    ss << std::put_time(std::gmtime(&expires_time_t), "%Y-%m-%d %H:%M:%S");
    *expires_at = ss.str();
    
    std::stringstream sql;
    sql << "INSERT INTO user_sessions (session_id, user_id, expires_at) VALUES ('"
        << *session_id << "', " << user_id << ", '" << *expires_at << "')";
    
    return MysqlQuery(_mysql, sql.str());
}

bool TableUserSession::ValidateSession(const std::string& session_id, Json::Value* user_info) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    std::stringstream sql;
    sql << "SELECT s.user_id, u.username, u.email, s.expires_at "
        << "FROM user_sessions s JOIN users u ON s.user_id = u.user_id "
        << "WHERE s.session_id='" << session_id << "' AND s.expires_at > NOW()";
    
    if (!MysqlQuery(_mysql, sql.str())) {
        return false;
    }
    
    MYSQL_RES* res = mysql_store_result(_mysql);
    if (res == NULL) {
        return false;
    }
    
    MYSQL_ROW row = mysql_fetch_row(res);
    if (row == NULL) {
        mysql_free_result(res);
        return false;
    }
    
    (*user_info)["user_id"] = atoi(row[0]);
    (*user_info)["username"] = row[1];
    (*user_info)["email"] = row[2];
    
    mysql_free_result(res);
    return true;
}

bool TableUserSession::DeleteSession(const std::string& session_id) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    std::stringstream sql;
    sql << "DELETE FROM user_sessions WHERE session_id='" << session_id << "'";
    
    return MysqlQuery(_mysql, sql.str());
}

bool TableUserSession::RefreshSession(const std::string& session_id, std::string* new_expires_at) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    // 设置新的过期时间为24小时后
    auto now = std::chrono::system_clock::now();
    auto expires = now + std::chrono::hours(24);
    auto expires_time_t = std::chrono::system_clock::to_time_t(expires);
    
    std::stringstream ss;
    ss << std::put_time(std::gmtime(&expires_time_t), "%Y-%m-%d %H:%M:%S");
    *new_expires_at = ss.str();
    
    std::stringstream sql;
    sql << "UPDATE user_sessions SET expires_at='" << *new_expires_at 
        << "' WHERE session_id='" << session_id << "'";
    
    return MysqlQuery(_mysql, sql.str());
}

bool TableUserSession::CleanExpiredSessions() {
    std::unique_lock<std::mutex> lock(_mtx);
    
    std::string sql = "DELETE FROM user_sessions WHERE expires_at <= NOW()";
    return MysqlQuery(_mysql, sql);
}

// TableVideoLikes 实现
bool TableVideoLikes::LikeVideo(int video_id, int user_id, bool like) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    // 开始事务
    if (!MysqlQuery(_mysql, "START TRANSACTION")) {
        return false;
    }
    
    bool success = false;
    std::stringstream sql;
    
    if (like) {
        // 添加点赞记录
        sql << "INSERT INTO video_likes (video_id, user_id) VALUES (" 
            << video_id << ", " << user_id << ") ON DUPLICATE KEY UPDATE like_id=like_id";
        
        if (MysqlQuery(_mysql, sql.str())) {
            // 更新点赞计数
            sql.str("");
            sql << "UPDATE table_video SET like_count = like_count + 1 WHERE id = " << video_id;
            success = MysqlQuery(_mysql, sql.str());
        }
    } else {
        // 删除点赞记录
        sql << "DELETE FROM video_likes WHERE video_id = " << video_id 
            << " AND user_id = " << user_id;
        
        if (MysqlQuery(_mysql, sql.str())) {
            // 更新点赞计数
            sql.str("");
            sql << "UPDATE table_video SET like_count = GREATEST(0, like_count - 1) WHERE id = " << video_id;
            success = MysqlQuery(_mysql, sql.str());
        }
    }
    
    // 提交或回滚事务
    if (success) {
        MysqlQuery(_mysql, "COMMIT");
    } else {
        MysqlQuery(_mysql, "ROLLBACK");
    }
    
    return success;
}

bool TableVideoLikes::GetLikeStatus(int video_id, int user_id, bool* liked, int* like_count) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    // 检查用户是否点赞
    std::stringstream sql;
    sql << "SELECT COUNT(*) FROM video_likes WHERE video_id = " << video_id 
        << " AND user_id = " << user_id;
    
    if (!MysqlQuery(_mysql, sql.str())) {
        return false;
    }
    
    MYSQL_RES* res = mysql_store_result(_mysql);
    if (res == NULL) {
        return false;
    }
    
    MYSQL_ROW row = mysql_fetch_row(res);
    *liked = (row != NULL && atoi(row[0]) > 0);
    mysql_free_result(res);
    
    // 获取总点赞数
    sql.str("");
    sql << "SELECT like_count FROM table_video WHERE id = " << video_id;
    
    if (!MysqlQuery(_mysql, sql.str())) {
        return false;
    }
    
    res = mysql_store_result(_mysql);
    if (res == NULL) {
        return false;
    }
    
    row = mysql_fetch_row(res);
    *like_count = (row != NULL) ? atoi(row[0]) : 0;
    mysql_free_result(res);
    
    return true;
}

bool TableVideoLikes::GetVideoLikeCount(int video_id, int* like_count) {
    std::unique_lock<std::mutex> lock(_mtx);
    
    std::stringstream sql;
    sql << "SELECT like_count FROM table_video WHERE id = " << video_id;
    
    if (!MysqlQuery(_mysql, sql.str())) {
        return false;
    }
    
    MYSQL_RES* res = mysql_store_result(_mysql);
    if (res == NULL) {
        return false;
    }
    
    MYSQL_ROW row = mysql_fetch_row(res);
    *like_count = (row != NULL) ? atoi(row[0]) : 0;
    mysql_free_result(res);
    
    return true;
}

} 